package org.setec.manager;

import org.setec.InstrumentMocker;
import org.setec.manager.stubview.StorageViewTransformer;
import org.setec.utils.io.Stub;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ManagerServlet implements Servlet {
    private ServletConfig config;
    private boolean instrumentationDone = false;

    public void init(ServletConfig config) throws ServletException {
        this.config = config;

        int x = 0;
        for( int i = 0; i < 10000000; i++){
            x += 123456;
        }

        InputStream configStream = null;
        try {
            configStream = config.getServletContext().getResource("WEB-INF/CHEDECPMimicMockerConfig.xml").openStream();
            try {
                InstrumentMocker.loadConfigurationAsStream(configStream);
                InstrumentMocker.instrumentClasses();
                instrumentationDone = true;
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServletException(e);
        }
    }

    public void destroy() {
    }

    public ServletConfig getServletConfig() {
        return config;
    }

    public String getServletInfo() {
        return "Mimic Mocker Manager";
    }

    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html><head>");
        out.println("<title>Mimic Mocker Manager</title>");
        out.println("</head>");
        out.println("<body>");
        if (instrumentationDone) {
            out.println("<h1>Instrumentation completed</h1>");
        } else {
            out.println("<h1>Instrumentation not completed</h1>");
        }

        StorageViewTransformer storageViewTransformer = new StorageViewTransformer();
        List stubNames = storageViewTransformer.getStorageStubList(InstrumentMocker.getConfiguration().getStorage());
        List stubs = storageViewTransformer.loadStubs(stubNames);

        StringBuffer stubInfo = new StringBuffer();

        for (int i = 0; stubNames != null && i < stubNames.size(); i++) {
            String stubName = (String) stubNames.get(i);
            Stub stub = (Stub) stubs.get(i);
            if (stub == null) {
                continue;
            }
            stubInfo.append("<p>").append(stubName).append("<br/>");
            stubInfo.append(stub.getClassName()).append("<br/>");
            stubInfo.append(stub.getMethodName()).append("<hr/>");
            for (int j = 0; j < stub.getArgs().length; j++) {
                stubInfo.append(stub.getArgs()[i].getClass().getName()).append("<br/>");
                renderObject(stubInfo, stub.getArgs()[i]);
                stubInfo.append("<br/>");
            }
            stubInfo.append("<hr/></p>");
        }

        out.println(stubInfo.toString());
        out.println("</body></html>");
        out.close();
    }

    private String renderObject(StringBuffer stringBuffer, Object obj) {
        if (obj == null) {
            return "(null)<br/>";
        }

        stringBuffer.append("(").append(obj.getClass().getName()).append("):<br/>");

        if (obj.getClass().isArray()) {
            Object[] arr = (Object[]) obj;
            for (int i = 0; i < arr.length; i++) {
                stringBuffer.append("&nbsp;&nbsp;&nbsp;&nbsp;[").append(i).append("] ");
                renderObject(stringBuffer, arr[i]);
            }
        }

        if (obj instanceof Collection) {
            Collection collection = (Collection) obj;
            Iterator it = collection.iterator();
            for (int i = 0; i < collection.size(); i++) {
                stringBuffer.append("&nbsp;&nbsp;&nbsp;&nbsp;[").append(i).append("] ");
                renderObject(stringBuffer, it.next());
            }
        }

        if (obj instanceof Map) {
            Map map = (Map) obj;
            Iterator it = map.keySet().iterator();
            for (int i = 0; i < map.keySet().size(); i++) {
                Object key = it.next();
                stringBuffer.append("&nbsp;&nbsp;&nbsp;&nbsp;[").append(i).append("]:\"").append(key).append("\"=");//todo: add render for object keys
                renderObject(stringBuffer, map.get(key));
            }
        }


        return null;
    }




}
